#include<func.h>
#include"train.h"
#include"fo.h"
#include"md5.h"
int main(int argc, char *argv[])
{
    fo();
    //1. 创建套接字
    int clientfd =  socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(clientfd, -1, "socket");

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);

    //2. 向服务器发起建立连接的请求
    int ret = connect(clientfd, 
                      (struct sockaddr *)&serveraddr, 
                      sizeof(serveraddr));
    ERROR_CHECK(ret, -1, "connect");
    printf("connect has completed.\n");

    fd_set rdset;
    printf("\n\
           //**************************************//\n\
           //*             **用户登录**           *//\n\           
           //**************************************//\n");
        printf("_______________________________________________________________________\n");
    printf("put name:\n");


    //进行登录和注册
    while(1){
lable2://注册成功后跳到这里进行登录
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO,&rdset);
        FD_SET(clientfd,&rdset);
        char buff[1000]={0};
        select(10,&rdset,NULL,NULL,NULL);
        char name[1024]={0};//键盘上输入的名字
        char *passwd;//键盘上输入的密码
        char username[20]={0};//键盘上输入的名字去掉\n
        read(STDIN_FILENO,name,sizeof(name));
        passwd=getpass("put passwd:");//输入密码

        printf("name:%s\n",name);
        //printf("passwd is %s\n",passwd);

        memcpy(username,name,strlen(name)-1);//去掉名字里面的\n
        printf("username:%s\n",username);
        //发送用户名
        trainSend(username,clientfd);

        //接收反馈
        char a[30]={0};
        trainRecv(a,clientfd);
        printf("a is:%s\n",a);

        if(memcmp(a,"failname",strlen(a))!=0){
            //接收服务器发送过来的盐之
            char salt[21]={0};//盐值
            char cryptpasswd[20]={0};//密文
            trainRecv(salt,clientfd);
            printf("---recvsalt is:%s\n",salt);

            //生成密文
            strcpy(cryptpasswd,crypt(passwd,salt));
            printf("----cryptpasswd is:%s\n",cryptpasswd);

            //发送密文
            trainSend(cryptpasswd,clientfd);

            //接收服务端，是否成功登录
            char success[20]={0};
            trainRecv(success,clientfd);
            if(memcmp(success,"success",strlen(success))==0){
                break;
            }else{
                printf("passwd error\n");
                printf("\n\
                       //**************************************//\n\
                       //*             **用户登录**           *//\n\           
                       //**************************************//\n");
                    printf("_______________________________________________________________________\n");
                printf("put name:\n");
                continue;
            }
        }else{
            //注册失败跳转到这里
lable1:
            printf("---------------用户不存在-------------\n");
            printf("\n");
            printf("----------------是否注册--------------\n");
            printf("1.用户注册\n");
            printf("2.返回登录\n");
            printf("other num:退出程序\n");
            printf("--------------------------------------\n");
            printf("put select number:");
            int i[1]={0};
            scanf("%d",i);
            printf("i is:%d\n",i[0]);
            if(i[0]==1){
                char a[5]="1";//告诉服务器进行注册
                trainSend(a,clientfd);
                char registerName[20]={0};
                char registerPasswd[10]={0};
                printf("---------------用户注册---------------\n");

                printf("put name:\n");
                //输入名字
                read(STDIN_FILENO,registerName,sizeof(name));
                trainSend(registerName,clientfd);

                passwd=getpass("put passwd:");//输入密码
                memcpy(registerPasswd,passwd,strlen(passwd));

                trainSend(registerPasswd,clientfd);
                printf("--register name:%s\n",registerName);
                printf("passwd is %s\n",registerPasswd);


                char b[1000]={0};
                trainRecv(b,clientfd);//接收服务反馈
                if(memcmp(b,"1",strlen(b))==0){//注册成功
                    printf("register is success\n");
                    printf("\n\
                           //**************************************//\n\
                           //*             **用户登录**           *//\n\           
                           //**************************************//\n");
                        printf("_______________________________________________________________________\n");
                    printf("put name:\n");
                    goto lable2;//注册成功后，跳到登录界面
                }else{
                    printf("register is fail\n");
                    printf("error is:%s\n",b);
                    goto lable1;//跳转到是否注册
                }
            }else if(i[0]==2){
                char a1[2]="2";
                trainSend(a1,clientfd);
                printf("put name:\n");
                continue;
            }else{
                exit(0);
            }
        }
    }
    printf("--------------------------------\n");
    printf("please enter handl order:\n");
    while(1){

        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO,&rdset);
        FD_SET(clientfd,&rdset);
        char buff[1000]={0};
        select(10,&rdset,NULL,NULL,NULL);
        if(FD_ISSET(STDIN_FILENO,&rdset)){
            ret = read(STDIN_FILENO,buff,sizeof(buff));
            ERROR_CHECK(ret,-1,"send");

            char order[100]={0};//接收命令的数组
            char filename[100]={0};//接收文件名的数组
            splitChar(buff,order,filename);

            if(strcmp(order,"puts") == 0){
                char md5[100]={0};
                struct stat filesize;
                char size[100]={0};
                //生成文件MD5码
                md5Create(filename,md5);

                //生成文件大小
                stat(filename,&filesize);

                printf("%s md5:%s\n",filename,md5);

                trainSendPlus(buff,clientfd);

                //发送md5码
                trainSend(md5,clientfd);
                //发送文件大小
                sprintf(size,"%ld",filesize.st_size);
                printf("%s byte:%s\n",filename,size);

                trainSend(size,clientfd);

                int length;
                ret = recv(clientfd, &length, 4, MSG_WAITALL);
                // printf(">>1. recv from server filelength:%d\n", length);

                char recvBuff[BUFFSIZE] = {0};//应用层接收缓冲区
                ret = recv(clientfd, recvBuff, length, MSG_WAITALL);

                //为1是服务器端没有这个文件
                //为0是服务器端有这个文件，就不用传了
                if(memcmp(recvBuff,"1",strlen(recvBuff))==0){
                    transferFile(clientfd,filename);

                }else{
                    continue;
                }

            }else if(strcmp(order,"gets")==0){
                trainSendPlus(buff,clientfd);
                printf("enter gets\n");
                //本地存在同名文件，则不传
                int fd = open(filename,O_RDONLY);
                if(fd != -1){
                    printf("enter 1  open\n");
                    printf("have this file,can not gets!\n");
                    char a2[2]="5";
                    trainSend(a2,clientfd);

                    continue;
                }else{
                    printf("enter 2 open\n");
                    char a2[2]="8";
                    trainSend(a2,clientfd);

                    //trainSendPlus(buff,clientfd);
                }
            }else{
                trainSendPlus(buff,clientfd);
            }
            //memset(buff,0,sizeof(buff));
        }
        if(FD_ISSET(clientfd,&rdset)){
            //如果服务器端用的小火车发，就用这段代码。
            int length;
            ret = recv(clientfd, &length, 4, MSG_WAITALL);
            // printf(">>1. recv from server filelength:%d\n", length);

            char recvBuff[BUFFSIZE] = {0};//应用层接收缓冲区
            ret = recv(clientfd, recvBuff, length, MSG_WAITALL);
            char order[100]={0};//接收命令的数组
            char filename[100]={0};//接收文件名的数组
            //splitChar(recvBuff,order,filename);

            if(strncmp(recvBuff,"gets",4)==0){
                for(int i=0,j=5;j<strlen(recvBuff);i++,j++){
                    filename[i]=recvBuff[j];
                }
                printf("enter gets\n");
                /* //本地存在同名文件，则不传
                   int fd = open(filename,O_RDONLY);
                   if(fd != -1){
                   printf("enter 1  open\n");
                   printf("have this file,can not gets!\n");
                   char a2[2]="5";
                   trainSend(a2,clientfd);
                //continue;
                }else{
                printf("enter 2 open\n");
                char a2[2]="8";
                trainSend(a2,clientfd);
                recv_file(clientfd,filename);
                }*/
                recv_file(clientfd,filename);
            }else{
                printf(">>2. recv from server:%s\n", recvBuff);
                printf("---------------------\n");
            }
        }
    }
    /*
    //3. 下载文件
    //3.1 接收文件的名字
    int length;
    ret = recv(clientfd, &length, 4, MSG_WAITALL);
    printf(">>1. filename length:%d\n", length);

    //提出新的需求: 需要接收确定字节数的数据
    char recvBuff[1000] = {0};//应用层接收缓冲区
    ret = recv(clientfd, recvBuff, length, MSG_WAITALL); printf(">>2. recv filename:%s\n", recvBuff);

    //3.2 在客户端本地，要创建文件
    int fileFd = open(recvBuff, O_CREAT|O_RDWR, 0644);
    //3.3 接收文件的大小
    off_t fileSize;
    ret = recv(clientfd, &length, 4, MSG_WAITALL);
    printf("length: %d\n", length);
    ret = recv(clientfd, &fileSize, sizeof(fileSize), MSG_WAITALL);
    printf("> file length: %ld\n", fileSize);

    ftruncate(fileFd, fileSize);

    //3.4 接收文件的内容
    char * pbuf = (char*) mmap(NULL, fileSize, 
    PROT_READ|PROT_WRITE, 
    MAP_SHARED, fileFd, 0);
    ret = recv(clientfd, pbuf, fileSize, MSG_WAITALL);

    close(fileFd);
    munmap(pbuf, fileSize);*/
    close(clientfd);
}
